package com.mazaiting.generator.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.mazaiting.common.core.domain.result.ResultCode;
import com.mazaiting.common.core.ex.exceptions.BusinessException;
import com.mazaiting.generator.config.GenDataSource;
import com.mazaiting.generator.config.GeneratorProperties;
import com.mazaiting.generator.config.query.AbstractQuery;
import com.mazaiting.generator.constants.GenConstant;
import com.mazaiting.generator.domain.entity.TemplateFileEntity;
import com.mazaiting.generator.domain.info.FieldInfo;
import com.mazaiting.generator.domain.vo.TableVO;
import com.mazaiting.generator.enums.DbTypeEnum;
import com.mazaiting.web.utils.WebUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 代码生成器 工具类
 */
@Slf4j
public class GenUtil {


    /**
     * 根据数据源，获取全部数据表
     *
     * @param datasource 数据源
     */
    public static List<TableVO> getTableList(GenDataSource datasource) {
        List<TableVO> tableList = new ArrayList<>();
        try {
            AbstractQuery query = datasource.getDbQuery();
            Connection connection = datasource.getConnection();
            //查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(query.tableSql(null));
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                TableVO tableVO = new TableVO();
                tableVO.setId(IdWorker.getId());
                tableVO.setName(rs.getString(query.tableName()));
                tableVO.setComment(rs.getString(query.tableComment()));
                tableList.add(tableVO);
            }
        } catch (Exception e) {
            log.error("获取数据源表列表失败: {}", e.getMessage());
        } finally {
            DbUtil.close(datasource.getConnection());
        }

        return tableList;
    }

    /**
     * 获取表字段列表
     *
     * @param datasource 数据源
     * @param tableName  表名
     */
    public static List<FieldInfo> getTableFieldList(GenDataSource datasource, String tableName) {
        List<FieldInfo> fieldInfoList = new ArrayList<>();

        try {
            AbstractQuery query = datasource.getDbQuery();
            // 获取查询表字段 SQL
            String tableFieldsSql = query.tableFieldsSql();
            if (datasource.getDbTypeEnum() == DbTypeEnum.Oracle) {
                DatabaseMetaData md = datasource.getConnection().getMetaData();
                tableFieldsSql = String.format(tableFieldsSql.replace("#schema", md.getUserName()), tableName);
            } else {
                tableFieldsSql = String.format(tableFieldsSql, tableName);
            }
            Connection connection = datasource.getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(tableFieldsSql);
            ResultSet rs = preparedStatement.executeQuery();
            while (rs.next()) {
                FieldInfo fieldInfo = new FieldInfo();
                // 设置字段名
                fieldInfo.setFieldName(rs.getString(query.fieldName()));
                // 设置字段类型
                String fieldType = rs.getString(query.fieldType());
                if (fieldType.contains(" ")) {
                    fieldType = fieldType.substring(0, fieldType.indexOf(" "));
                }
                fieldInfo.setFieldType(fieldType);
                // 设置字段说明
                fieldInfo.setFieldComment(rs.getString(query.fieldComment()));
                String key = rs.getString(query.fieldKey());
                // 设置是否主键
                fieldInfo.setPrimaryKey(StringUtils.hasLength(key) && GenConstant.PREFIX_PRI.equalsIgnoreCase(key));

                fieldInfoList.add(fieldInfo);
            }
        } catch (Exception e) {
            log.error("获取表字段信息失败: {}", e.getMessage());
        }

        return fieldInfoList;
    }

    /**
     * 根据数据源，获取指定数据表
     *
     * @param datasource 数据源
     * @param tableName  表名
     */
    public static TableVO getTable(GenDataSource datasource, String tableName) throws BusinessException {
        try {
            AbstractQuery query = datasource.getDbQuery();
            // 获取数据库链接
            Connection connection = datasource.getConnection();
            // 查询数据
            PreparedStatement preparedStatement = connection.prepareStatement(query.tableSql(tableName));
            ResultSet rs = preparedStatement.executeQuery();
            if (rs.next()) {
                TableVO tableVO = new TableVO();
                // 设置表名
                tableVO.setName(rs.getString(query.tableName()));
                // 设置表说明
                tableVO.setComment(rs.getString(query.tableComment()));
                return tableVO;
            }
        } catch (Exception e) {
            log.error("获取表信息失败: {}", e.getMessage());
        }
        throw new BusinessException(ResultCode.COMMON_FAIL.getCode(), "数据库表不存在：" + tableName);
    }

    /**
     * 获取模块名
     *
     * @param allPackageName 包名
     * @return 模块名
     */
    public static String getPackageName(String allPackageName) {
        return StrUtil.subBefore(allPackageName, ".", true);
    }

    /**
     * 获取模块名
     *
     * @param allPackageName 包名
     * @return 模块名
     */
    public static String getModuleName(String allPackageName) {
        return StrUtil.subAfter(allPackageName, ".", true);
    }

    /**
     * 获取功能名
     *
     * @param tableName 表名
     * @return 功能名
     */
    public static String getFunctionName(String tableName) {
        String functionName = StrUtil.subAfter(tableName, "_", true);
        if (StrUtil.isBlank(functionName)) {
            functionName = tableName;
        }

        return functionName;
    }

    /**
     * 获取模板文件内容
     * @return 文件内容
     */
    public static String getFileContent(GeneratorProperties properties, TemplateFileEntity templateFileEntity) {
        // 模板内容
        String templateContent = "";
        try {
            if (templateFileEntity.getLocation() == 0) {
                // 模板名
                String templateName = templateFileEntity.getFilePath() + File.separator + templateFileEntity.getFileName();
                templateContent = WebUtil.getContent(properties.getTemplate() + "/" + templateName);
            } else {
                // 文件保存路径 ${user.home}/.generator/{groupId}/{form.filePath}
                String filePath = GenConstant.USER_DIRECTORY + File.separator + templateFileEntity.getGroupId();
                if (StringUtils.hasLength(templateFileEntity.getFilePath())) {
                    filePath = filePath + File.separator + templateFileEntity.getFilePath();
                }
                // 读取文件内容
                File file = new File(filePath, templateFileEntity.getFileName());
                templateContent = FileUtil.readUtf8String(file);
            }
        } catch (Exception e){
            log.error("获取文件内容失败: " + e.getMessage());
        }
        return templateContent;
    }
}
